/**
 * TorrentJEDI
 * 		Torrent Java Episode Download Interface
 */
package torrentjedi.ui;

import java.awt.BorderLayout;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JSplitPane;
import javax.swing.JToolBar;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.EtchedBorder;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;

import torrentjedi.core.Configuration;
import torrentjedi.core.RSSChannel;
import torrentjedi.core.TorrentSource;
import torrentjedi.util.JEDIUtils;

/**
 * @author Alper Kokmen
 *
 */
public class TorrentJEDI implements ActionListener {
	private static final int FRAME_WIDTH = 800;
	private static final int FRAME_HEIGHT = 600;
	
	private List<String> jFrameList = new ArrayList<String>();
	private List<RSSChannel> rssChannels = new ArrayList<RSSChannel>();
	
	private Configuration configuration = null;
	
	private JFrame jFrame = null;
	private JPanel jContentPane = null;
	private JDialog aboutDialog = null;
	private JPanel aboutContentPane = null;
	private JLabel aboutVersionLabel = null;
	private JProgressBar jProgressBar = null;
	private JPanel jStatusPanel = null;
	private JLabel jStatusLabel = null;
	private JToolBar jToolBar = null;
	private JSplitPane jSplitPane = null;
	private JButton jNewSourceButton = null;
	private JButton jOpenSourceButton = null;
	private JButton jFetchButton = null;
	private JButton jSettingsButton = null;
	private JButton jStatisticsButton = null;
	private JButton jAboutButton = null;
	private JButton jExitButton = null;
	private JPanel jLeftPanel = null;
	private JList jList = null;
	private JLabel jLeftPanelLabel = null;
	private JPanel jLeftHeaderPanel = null;
	private JPanel jRightPanel = null;
	private JPanel jRightHeaderPanel = null;
	private JLabel jDesktopPaneLabel = null;
	private JDesktopPane jDesktopPane = null;
	/**
	 * This method initializes jProgressBar	
	 * 	
	 * @return javax.swing.JProgressBar	
	 */
	private JProgressBar getJProgressBar() {
		if (jProgressBar == null) {
			jProgressBar = new JProgressBar();
			jProgressBar.setMinimum(0);
			jProgressBar.setMaximum(100);
			jProgressBar.setValue(0);
			jProgressBar.setStringPainted(true);
			jProgressBar.setPreferredSize(new Dimension(300, 15));
		}
		return jProgressBar;
	}

	/**
	 * This method initializes jStatusPanel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getJStatusPanel() {
		if (jStatusPanel == null) {
			jStatusLabel = new JLabel();
			jStatusLabel.setText("...");
			jStatusLabel.setPreferredSize(new Dimension(500, 15));
			jStatusPanel = new JPanel();
			jStatusPanel.setLayout(new BorderLayout());
			jStatusPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
			jStatusPanel.add(jStatusLabel, BorderLayout.WEST);
			jStatusPanel.add(getJProgressBar(), BorderLayout.EAST);
		}
		return jStatusPanel;
	}

	/**
	 * This method initializes jToolBar	
	 * 	
	 * @return javax.swing.JToolBar	
	 */
	private JToolBar getJToolBar() {
		if (jToolBar == null) {
			jToolBar = new JToolBar();
			jToolBar.setLayout(new FlowLayout());
			jToolBar.setToolTipText("");
			jToolBar.setFloatable(false);
			jToolBar.setPreferredSize(new Dimension(800, 50));
			jToolBar.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
			jToolBar.add(getJNewSourceButton());
			jToolBar.add(getJOpenSourceButton());
			jToolBar.add(getJFetchButton());
			jToolBar.add(getJSettingsButton());
			jToolBar.add(getJStatisticsButton());
			jToolBar.add(getJAboutButton());
			jToolBar.add(getJExitButton());
		}
		return jToolBar;
	}

	/**
	 * This method initializes jSplitPane	
	 * 	
	 * @return javax.swing.JSplitPane	
	 */
	private JSplitPane getJSplitPane() {
		if (jSplitPane == null) {
			jSplitPane = new JSplitPane();
			jSplitPane.setDividerLocation(150);
			jSplitPane.setOneTouchExpandable(false);
			jSplitPane.setResizeWeight(0.0D);
			jSplitPane.setContinuousLayout(true);
			jSplitPane.setLeftComponent(getJLeftPanel());
			jSplitPane.setRightComponent(getJRightPanel());
			jSplitPane.setDividerSize(5);
		}
		return jSplitPane;
	}

	/**
	 * This method initializes jNewSourceButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getJNewSourceButton() {
		if (jNewSourceButton == null) {
			jNewSourceButton = new JButton();
			jNewSourceButton.setPreferredSize(new Dimension(100, 40));
			jNewSourceButton.setText("New Source");
			jNewSourceButton.setSize(new Dimension(100, 40));
			jNewSourceButton.setHorizontalAlignment(SwingConstants.CENTER);
			jNewSourceButton.addActionListener(this);
		}
		return jNewSourceButton;
	}

	/**
	 * This method initializes jOpenSourceButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getJOpenSourceButton() {
		if (jOpenSourceButton == null) {
			jOpenSourceButton = new JButton();
			jOpenSourceButton.setPreferredSize(new Dimension(100, 40));
			jOpenSourceButton.setSize(new Dimension(100, 40));
			jOpenSourceButton.setText("Open Source");
			jOpenSourceButton.addActionListener(this);
		}
		return jOpenSourceButton;
	}

	/**
	 * This method initializes jFetchButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getJFetchButton() {
		if (jFetchButton == null) {
			jFetchButton = new JButton();
			jFetchButton.setPreferredSize(new Dimension(100, 40));
			jFetchButton.setSize(new Dimension(100, 40));
			jFetchButton.setText("Fetch");
			jFetchButton.addActionListener(this);
		}
		return jFetchButton;
	}

	/**
	 * This method initializes jSettingsButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getJSettingsButton() {
		if (jSettingsButton == null) {
			jSettingsButton = new JButton();
			jSettingsButton.setPreferredSize(new Dimension(100, 40));
			jSettingsButton.setText("Settings");
			jSettingsButton.addActionListener(this);
		}
		return jSettingsButton;
	}

	/**
	 * This method initializes jStatisticsButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getJStatisticsButton() {
		if (jStatisticsButton == null) {
			jStatisticsButton = new JButton();
			jStatisticsButton.setPreferredSize(new Dimension(100, 40));
			jStatisticsButton.setText("Statistics");
			jStatisticsButton.addActionListener(this);
		}
		return jStatisticsButton;
	}

	/**
	 * This method initializes jAboutButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getJAboutButton() {
		if (jAboutButton == null) {
			jAboutButton = new JButton();
			jAboutButton.setPreferredSize(new Dimension(100, 40));
			jAboutButton.setText("About");
			jAboutButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					getAboutDialog().setVisible(true);
				}
			});
		}
		return jAboutButton;
	}

	/**
	 * This method initializes jExitButton	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getJExitButton() {
		if (jExitButton == null) {
			jExitButton = new JButton();
			jExitButton.setPreferredSize(new Dimension(100, 40));
			jExitButton.setText("Exit");
			jExitButton.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					final int optionResult = JOptionPane.showConfirmDialog(getJContentPane(), "Are you sure you want to exit?", "Exit Confirmation", JOptionPane.YES_NO_OPTION); 
					if (optionResult == 0) {
						System.exit(0);
					}
				}
			});
		}
		return jExitButton;
	}

	/**
	 * This method initializes jLeftPanel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getJLeftPanel() {
		if (jLeftPanel == null) {
			jLeftPanelLabel = new JLabel();
			jLeftPanelLabel.setText("Torrent Sources");
			jLeftPanelLabel.setFont(new Font("Dialog", Font.BOLD, 14));
			jLeftPanel = new JPanel();
			jLeftPanel.setLayout(new BorderLayout());
			jLeftPanel.setPreferredSize(new Dimension(150, 400));
			jLeftPanel.add(getJList(), BorderLayout.CENTER);
			jLeftPanel.add(getJLeftHeaderPanel(), BorderLayout.NORTH);
		}
		return jLeftPanel;
	}

	/**
	 * This method initializes jList	
	 * 	
	 * @return javax.swing.JList	
	 */
	private JList getJList() {
		if (jList == null) {
			jList = new JList();
			jList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
			jList.setVisibleRowCount(20);
			jList.addMouseListener(new java.awt.event.MouseListener() {
				public void mouseClicked(java.awt.event.MouseEvent e) {
					JList list = (JList) e.getSource();
					System.out.println("DEBUG@TorrentJEDI:TorrentJEDI mouseClicked [" + list.getSelectedIndex() + "]");
					
					if (getJFrameList().contains(list.getSelectedValue().toString())) {
						System.out.println("DEBUG@TorrentJEDI:TorrentJEDI mouseClicked [" + list.getSelectedIndex() + " is already open]");
						// TODO focus to the selected element
					} else {
						JInternalFrame frame = new JInternalFrame();
						frame.setTitle(list.getSelectedValue().toString());
						frame.setClosable(true);
						frame.setIconifiable(true);
						frame.setVisible(true);
						frame.setResizable(true);
						frame.setMaximizable(true);
						frame.getContentPane().setSize(200, 200);
						frame.setSize(200, 200);
						frame.setRequestFocusEnabled(true);
						
						frame.addAncestorListener(new AncestorListener() {
							@Override
							public void ancestorAdded(AncestorEvent event) {
//								JInternalFrame frame = (JInternalFrame) event.getSource();
//								System.out.println("DEBUG@TorrentJEDI:TorrentJEDI ancestorAdded [" + frame.getTitle() + "]");
								// TODO focus to the added element
							}

							@Override
							public void ancestorMoved(AncestorEvent event) {
								// not needed at the moment
							}

							@Override
							public void ancestorRemoved(AncestorEvent event) {
								JInternalFrame frame = (JInternalFrame) event.getSource();
//								System.out.println("DEBUG@TorrentJEDI:TorrentJEDI ancestorRemoved [" + frame.getTitle() + "]");
								getJFrameList().remove(frame.getTitle());
							}
						});
						
						getJDesktopPane().add(frame);
						getJFrameList().add(list.getSelectedValue().toString());
					}
					
				}
				public void mousePressed(java.awt.event.MouseEvent e) {
					// not needed at the moment
				}
				public void mouseReleased(java.awt.event.MouseEvent e) {
					// not needed at the moment
				}
				public void mouseEntered(java.awt.event.MouseEvent e) {
					// not needed at the moment
				}
				public void mouseExited(java.awt.event.MouseEvent e) {
					// not needed at the moment
				}
			});
		}
		return jList;
	}

	/**
	 * This method initializes jLeftHeaderPanel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getJLeftHeaderPanel() {
		if (jLeftHeaderPanel == null) {
			jLeftHeaderPanel = new JPanel();
			jLeftHeaderPanel.setLayout(new BorderLayout());
			jLeftHeaderPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
			jLeftHeaderPanel.setPreferredSize(new Dimension(118, 25));
			jLeftHeaderPanel.add(jLeftPanelLabel, BorderLayout.NORTH);
		}
		return jLeftHeaderPanel;
	}

	/**
	 * This method initializes jRightPanel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getJRightPanel() {
		if (jRightPanel == null) {
			jRightPanel = new JPanel();
			jRightPanel.setLayout(new BorderLayout());
			jRightPanel.add(getJRightHeaderPanel(), BorderLayout.NORTH);
			jRightPanel.add(getJDesktopPane(), BorderLayout.CENTER);
		}
		return jRightPanel;
	}

	/**
	 * This method initializes jRightHeaderPanel	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getJRightHeaderPanel() {
		if (jRightHeaderPanel == null) {
			jDesktopPaneLabel = new JLabel();
			jDesktopPaneLabel.setFont(new Font("Dialog", Font.BOLD, 14));
			jDesktopPaneLabel.setText("Torrent Source Window");
			jRightHeaderPanel = new JPanel();
			jRightHeaderPanel.setLayout(new BorderLayout());
			jRightHeaderPanel.setPreferredSize(new Dimension(165, 25));
			jRightHeaderPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
			jRightHeaderPanel.add(jDesktopPaneLabel, BorderLayout.NORTH);
		}
		return jRightHeaderPanel;
	}

	/**
	 * This method initializes jDesktopPane	
	 * 	
	 * @return javax.swing.JDesktopPane	
	 */
	private JDesktopPane getJDesktopPane() {
		if (jDesktopPane == null) {
			jDesktopPane = new JDesktopPane();
		}
		return jDesktopPane;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				TorrentJEDI application = new TorrentJEDI();
				application.getJFrame().setVisible(true);
				
				/*
				 * access core layer
				 */
				application.jStatusLabel.setText("Reading the main configuration file config.xml...");
				application.setConfiguration(JEDIUtils.readConfig());
				application.getJProgressBar().setValue(25);
				
				application.jStatusLabel.setText("Performing auto-load operation for desired sources...");
				application.setRssChannels(JEDIUtils.performAutoLoad(application.getConfiguration().getSourceConfiguration().getSources()));
				application.getJProgressBar().setValue(100);
				
				List<String> sources = new ArrayList<String>();
				for (TorrentSource source : application.getConfiguration().getSourceConfiguration().getSources()) {
					if (source.getAutoLoad()) {
						sources.add(source.getName());
					} else {
						sources.add("*" + source.getName());
					}
				}
				application.getJList().setListData(sources.toArray());
			}
		});
	}

	/**
	 * This method initializes jFrame
	 * 
	 * @return javax.swing.JFrame
	 */
	private JFrame getJFrame() {
		if (jFrame == null) {
			jFrame = new JFrame();
			jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			jFrame.setMinimumSize(new Dimension(FRAME_WIDTH, FRAME_HEIGHT));
			jFrame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
			jFrame.setContentPane(getJContentPane());
			jFrame.setTitle("TorrentJEDI");
			
			Toolkit toolkit = Toolkit.getDefaultToolkit();
			jFrame.setLocation(toolkit.getScreenSize().width / 2 - FRAME_WIDTH / 2, toolkit.getScreenSize().height / 2 - FRAME_HEIGHT / 2);
		}
		return jFrame;
	}

	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getJStatusPanel(), BorderLayout.SOUTH);
			jContentPane.add(getJToolBar(), BorderLayout.NORTH);
			jContentPane.add(getJSplitPane(), BorderLayout.CENTER);
		}
		return jContentPane;
	}

	/**
	 * This method initializes aboutDialog	
	 * 	
	 * @return javax.swing.JDialog
	 */
	private JDialog getAboutDialog() {
		if (aboutDialog == null) {
			aboutDialog = new JDialog(getJFrame(), true);
			aboutDialog.setTitle("About");
			aboutDialog.setLocationRelativeTo(getJContentPane());
			aboutDialog.setPreferredSize(new Dimension(112, 43));
			aboutDialog.setSize(new Dimension(112, 43));
			aboutDialog.setContentPane(getAboutContentPane());
		}
		return aboutDialog;
	}

	/**
	 * This method initializes aboutContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getAboutContentPane() {
		if (aboutContentPane == null) {
			aboutContentPane = new JPanel();
			aboutContentPane.setLayout(new BorderLayout());
			aboutContentPane.add(getAboutVersionLabel(), BorderLayout.CENTER);
		}
		return aboutContentPane;
	}

	/**
	 * This method initializes aboutVersionLabel	
	 * 	
	 * @return javax.swing.JLabel	
	 */
	private JLabel getAboutVersionLabel() {
		if (aboutVersionLabel == null) {
			aboutVersionLabel = new JLabel();
			aboutVersionLabel.setText("Version 1.0");
			aboutVersionLabel.setHorizontalAlignment(SwingConstants.CENTER);
		}
		return aboutVersionLabel;
	}

	@Override
	public void actionPerformed(ActionEvent a) {
		System.out.println("DEBUG@TorrentJEDI:TorrentJEDI actionPerformed [" + a.getSource() + "]");
		
		JButton source = (JButton) a.getSource();
		
		if (source.getText().equals("New Source")) {
			NewSourceDialog newSourceDialog = new NewSourceDialog(this.getJFrame(), getConfiguration());
			newSourceDialog.setVisible(true);
		} else if (source.getText().equals("Open Source")) {
			
		} else if (source.getText().equals("Fetch")) {
			
		} else if (source.getText().equals("Settings")) {
			
		} else if (source.getText().equals("Statistics")) {
			
		} else {
			
		}
	}

	/**
	 * @return the jFrameList
	 */
	public List<String> getJFrameList() {
		return jFrameList;
	}

	/**
	 * @param frameList the jFrameList to set
	 */
	public void setJFrameList(List<String> frameList) {
		jFrameList = frameList;
	}

	/**
	 * @return the configuration
	 */
	public Configuration getConfiguration() {
		return configuration;
	}

	/**
	 * @param configuration the configuration to set
	 */
	public void setConfiguration(Configuration configuration) {
		this.configuration = configuration;
	}

	/**
	 * @return the rssChannels
	 */
	public List<RSSChannel> getRssChannels() {
		return rssChannels;
	}

	/**
	 * @param rssChannels the rssChannels to set
	 */
	public void setRssChannels(List<RSSChannel> rssChannels) {
		this.rssChannels = rssChannels;
	}

}
